package com.mosai.alignpro.api;

import android.text.TextUtils;

import com.mosai.alignpro.api.services.DiagnosisService;
import com.mosai.alignpro.entity.AuditImageReq;
import com.mosai.alignpro.entity.ImageInfo;
import com.mosai.alignpro.entity.LastParam;
import com.mosai.alignpro.entity.ListData;
import com.mosai.alignpro.entity.PatientInfo;
import com.mosai.alignpro.entity.RnDiagnosisListParam;
import com.mosai.alignpro.util.DateUtils;
import com.mosai.alignpro.util.IntentUtils;
import com.mosai.alignpro.util.LogUtils;
import com.mosai.alignpro.util.Utils;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import okhttp3.ResponseBody;
import retrofit2.HttpException;
import retrofit2.Response;

/**
 * Created by Rays on 2020/3/25.
 */
public final class API {
    private static final String TAG = API.class.getSimpleName();
    public static final Consumer<Throwable> ON_ERROR = new OnError();
    public static final Consumer<Throwable> ON_ERROR_BASE = new OnErrorBase();

    public static Observable<ImageInfo> patientRead(ImageInfo info) {
        return HttpUtils.getInstance().getDiagnosisService()
                .patientRead(info.getImageId())
                .doOnNext(res -> info.setPatientIsRead(res.isPatientIsRead()))
                .observeOn(AndroidSchedulers.mainThread());
    }

    public static Observable<ImageInfo> auditImage(ImageInfo info) {
        AuditImageReq req;
        List<ImageInfo> histories = info.getHistories();
        if (histories == null || histories.isEmpty()) {
            req = getAuditImageReq(info);
        } else {
            ImageInfo temp = null;
            // 优先使用医生的编辑结果
            for (ImageInfo history : histories) {
                if (history.getDoctorInfo() != null && !history.getDoctorInfo().isAssistant()) {
                    temp = history;
                    break;
                }
                if (temp == null) {
                    temp = history;
                }
            }
            req = new AuditImageReq();
            req.setConditionStatus(temp.getConditionStatus());
            req.setDescribe(temp.getDescribe());
            req.setResult(temp.getCheckResultInfo());
            req.setAddResult(temp.getAddCheckResultInfo());
            req.setScoliosisType(temp.getScoliosisType());
        }
        return HttpUtils.getInstance().getDiagnosisService()
                .auditImage(info.getImageId(), req)
                .doOnNext(ImageInfo::init)
                .observeOn(AndroidSchedulers.mainThread());
    }

    public static Observable<ImageInfo> editImage(ImageInfo info) {
        AuditImageReq req = getAuditImageReq(info);
        return HttpUtils.getInstance().getDiagnosisService()
                .editImage(info.getImageId(), req)
                .doOnNext(ImageInfo::init)
                .observeOn(AndroidSchedulers.mainThread());
    }

    private static AuditImageReq getAuditImageReq(ImageInfo info) {
        AuditImageReq req = new AuditImageReq();
        Utils.setNewAIResult(info);
        req.setConditionStatus(info.getNewConditionStatus());
        req.setDescribe(info.getNewDescribe());
        req.setResult(info.getNewAIResult());
        req.setAddResult(info.getNewAddCheckResultInfo());
        req.setScoliosisType(info.getNewScoliosisType());
        return req;
    }

    public static Observable<ListData> getImageList(RnDiagnosisListParam rnParam) {
        LastParam param = rnParam.getLastParam();
        HashMap<String, String> map = new HashMap<>(3, 1);
        if (!TextUtils.isEmpty(param.getCategory())) {
            map.put(LastParam.PARAM_CATEGORY, param.getCategory());
        }
        map.put(LastParam.PARAM_SKIP_COUNT, String.valueOf(param.getSkipCount()));
        map.put(LastParam.PARAM_MAX_RESULT_COUNT, LastParam.DEFAULT_MAX_RESULT_COUNT);
        DiagnosisService diagnosisService = HttpUtils.getInstance().getDiagnosisService();
        return (IntentUtils.isPatientApp() ? diagnosisService.getImageListByPatient(map) : diagnosisService.getImageList(map))
                .doOnNext(res -> {
                    for (ImageInfo item : res.getItems()) {
                        ImageInfo lastOriginResult = item.getLastOriginResult();
                        if (lastOriginResult != null) {
                            item.setDoctorInfo(lastOriginResult.getDoctorInfo());
                            item.setDescribe(lastOriginResult.getDescribe());
                            item.setCheckResultInfo(lastOriginResult.getCheckResultInfo());
                            item.setAddCheckResultInfo(lastOriginResult.getAddCheckResultInfo());
                            item.setHistoryCreationTime(DateUtils.formatAuditDate(lastOriginResult.getCreationTime()));
//                            item.setAuditDate(lastOriginResult.getCreationTime());
                        } else {
                            item.setDoctorInfo(rnParam.getDoctorInfo());
                        }
                        item.resetEditStatus();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread());
    }

    public static Observable<ListData> getPatientImageList(RnDiagnosisListParam rnParam) {
        HashMap<String, String> map = new HashMap<>(2, 1);
        map.put(LastParam.PARAM_SKIP_COUNT, String.valueOf(rnParam.getLastParam().getSkipCount()));
        map.put(LastParam.PARAM_MAX_RESULT_COUNT, LastParam.DEFAULT_MAX_RESULT_COUNT);
        return HttpUtils.getInstance().getDiagnosisService()
                .getPatientImageList(rnParam.getPatientInfo().getId(), map)
                .doOnNext(res -> {
                    PatientInfo patientInfo = rnParam.getPatientInfo();
                    for (ImageInfo item : res.getItems()) {
                        item.setPatientInfo(patientInfo);
                        ImageInfo lastOriginResult = item.getLastOriginResult();
                        if (lastOriginResult != null) {
                            item.setDoctorInfo(lastOriginResult.getDoctorInfo());
                            item.setDescribe(lastOriginResult.getDescribe());
                            item.setCheckResultInfo(lastOriginResult.getCheckResultInfo());
                            item.setAddCheckResultInfo(lastOriginResult.getAddCheckResultInfo());
                            item.setHistoryCreationTime(DateUtils.formatAuditDate(lastOriginResult.getCreationTime()));
//                            item.setAuditDate(lastOriginResult.getCreationTime());
                        }
                        item.resetEditStatus();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread());
    }

    public static Observable<ImageInfo> getImageDetail(ImageInfo info) {
        DiagnosisService diagnosisService = HttpUtils.getInstance().getDiagnosisService();
        return (IntentUtils.isPatientApp() ? diagnosisService.getImageDetailByPatient(info.getImageId()) : diagnosisService.getImageDetail(info.getImageId()))
                .doOnNext(detail -> {
                    LogUtils.i(TAG, "isUiThread: " + Utils.isUiThread());
                    detail.setPatientInfo(info.getPatientInfo());
                    List<ImageInfo> histories = detail.getHistories();
                    for (ImageInfo item : histories) {
                        item.setPatientInfo(info.getPatientInfo());
                        item.setHistories(histories);
                        item.setImageId(detail.getId());
                        item.setAuditDate(detail.getAuditDate());
                        item.setHistory(true);
                        item.setHistoryCreationTime(DateUtils.formatAuditDate(item.getCreationTime()));
                        item.setCreationTime(detail.getCreationTime());
                        item.setTakeDate(detail.getTakeDate());
                        item.setUrl(detail.getUrl());
                        item.setPatientId(detail.getPatientId());
                        item.setImageType(detail.getImageType());
                        item.setStatus(detail.getStatus());
                        item.setAiOriginResult(detail.getAiOriginResult());
                        item.init();
//                        item.setStatus(ImageInfo.STATUS_AUDITED);
                    }
//                    Collections.reverse(detail.getHistories());
                })
                .observeOn(AndroidSchedulers.mainThread());
    }

    public static final class OnError implements Consumer<Throwable> {
        @Override
        public void accept(Throwable tr) throws Exception {
            ON_ERROR_BASE.accept(tr);
        }
    }

    public static final class OnErrorBase implements Consumer<Throwable> {
        @Override
        public void accept(Throwable tr) {
            if (tr instanceof HttpException) {
                HttpException httpException = (HttpException) tr;
                Response<?> response = httpException.response();
                String bodyStr = null;
                if (response != null) {
                    ResponseBody body = response.errorBody();
                    if (body != null) {
                        try {
                            bodyStr = body.string();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                LogUtils.e(TAG, "doOnError httpException"
                        + " code: " + httpException.code()
                        + " message: " + httpException.message()
                        + " body: " + bodyStr
                );
            } else {
                LogUtils.e(TAG, "doOnError", tr);
            }
        }
    }
}
